package com.dms.modules.product.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dms.common.api.ApiResponse;
import com.dms.common.exception.BusinessException;
import com.dms.common.security.SecurityUtils;
import com.dms.modules.product.dto.ProductDTO;
import com.dms.modules.product.dto.ProductSearchDTO;
import com.dms.modules.product.entity.Product;
import com.dms.modules.product.entity.ProductSku;
import com.dms.modules.product.service.ProductService;
import com.dms.modules.product.service.ProductSkuService;
import com.dms.modules.user.service.UserBehaviorService;
import com.dms.modules.user.dto.UserBehaviorDTO;
import com.dms.modules.product.vo.ProductDetailVO;
import com.dms.common.utils.FileUploadUtils;
import com.dms.modules.merchant.service.MerchantService;
import com.dms.modules.merchant.entity.Merchant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.dms.modules.product.vo.ProductSpecVO;
import com.dms.modules.product.vo.ProductSkuVO;
import org.apache.commons.lang3.StringUtils;
import java.math.BigDecimal;

/**
 * 商品基础控制器
 * 处理商品的基本CRUD操作和详情展示
 * 搜索和推荐相关功能已移至专门的控制器
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/api/v1/products")
@Api(tags = "商品接口")
public class ProductController extends BaseProductController {

    @Autowired
    private ProductService productService;

    @Autowired
    private ProductSkuService productSkuService;

    @Autowired
    private UserBehaviorService userBehaviorService;

    @Autowired
    private FileUploadUtils fileUploadUtils;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private ObjectMapper objectMapper;

    // ==================== 公共接口 ====================

    @GetMapping
    @ApiOperation("获取商品列表")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "pageNum", value = "页码", defaultValue = "1"),
        @ApiImplicitParam(name = "pageSize", value = "每页数量", defaultValue = "10"),
        @ApiImplicitParam(name = "categoryId", value = "分类ID", required = false),
        @ApiImplicitParam(name = "isNew", value = "是否新品", required = false),
        @ApiImplicitParam(name = "isHot", value = "是否热销", required = false),
        @ApiImplicitParam(name = "isRecommend", value = "是否推荐", required = false)
    })
    public ApiResponse<IPage<Product>> getProducts(
            @RequestParam(defaultValue = "1") @Min(value = 1, message = "页码不能小于1") Integer pageNum,
            @RequestParam(defaultValue = "10") @Min(value = 1, message = "每页条数不能小于1") Integer pageSize,
            @RequestParam(required = false) Long categoryId,
            @RequestParam(required = false) Boolean isNew,
            @RequestParam(required = false) Boolean isHot,
            @RequestParam(required = false) Boolean isRecommend) {
        try {
            IPage<Product> products = productService.getProducts(pageNum, pageSize, categoryId, isNew, isHot, isRecommend);
            return ApiResponse.success(products);
        } catch (Exception e) {
            log.error("获取商品列表失败", e);
            return ApiResponse.error("获取商品列表失败");
        }
    }

    @GetMapping("/{id}")
    @ApiOperation("获取商品详情")
    public ApiResponse<ProductDetailVO> getProductDetail(@PathVariable @NotNull(message = "商品ID不能为空") Long id) {
        try {
            // 增加商品浏览量
            productService.incrementViewCount(id);
            
            // 如果用户已登录，记录浏览行为
            if (SecurityUtils.isAuthenticated()) {
                Long userId = getUserId();
                if (userId != null) {
                    UserBehaviorDTO browseDTO = createSimpleBrowseDTO(id, "product_detail");
                    userBehaviorService.recordUserBrowse(userId, browseDTO);
                }
            }
            
            ProductDetailVO product = productService.getProductDetail(id);
            return ApiResponse.success(product);
        } catch (BusinessException e) {
            log.error("获取商品详情失败: id={}, error={}", id, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("获取商品详情失败: id={}", id, e);
            return ApiResponse.error("获取商品详情失败");
        }
    }


    @GetMapping("/{productId}/specs")
    @ApiOperation("获取商品规格信息")
    public ApiResponse<List<ProductSpecVO>> getProductSpecs(@PathVariable @NotNull(message = "商品ID不能为空") Long productId) {
        try {
            return ApiResponse.success(productService.getProductSpecs(productId));
        } catch (BusinessException e) {
            log.error("获取商品规格失败: {}", e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("获取商品规格失败", e);
            return ApiResponse.error("获取商品规格失败");
        }
    }

    @GetMapping("/{productId}/skus")
    @ApiOperation("获取商品SKU列表")
    public ApiResponse<List<ProductSkuVO>> getProductSkus(@PathVariable @NotNull(message = "商品ID不能为空") Long productId) {
        try {
            return ApiResponse.success(productService.getProductSkus(productId));
        } catch (BusinessException e) {
            log.error("获取商品SKU列表失败: {}", e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("获取商品SKU列表失败", e);
            return ApiResponse.error("获取商品SKU列表失败");
        }
    }
    @PostMapping("/search")
    @ApiOperation("搜索商品")
    public ApiResponse<IPage<Product>> searchProducts(@RequestBody ProductSearchDTO search) {
        try {
            IPage<Product> result = productService.search(search);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("搜索商品失败: {}", e.getMessage());
            return ApiResponse.error("搜索商品失败");
        }
    }

    @PutMapping("/{id}/view")
    @ApiOperation("增加商品浏览次数")
    public ApiResponse<Boolean> incrementViewCount(@PathVariable Long id) {
        try {
            boolean result = productService.incrementViewCount(id);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("增加商品浏览次数失败: id={}, error={}", id, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("增加商品浏览次数失败: id={}", id, e);
            return ApiResponse.error("增加商品浏览次数失败");
        }
    }

    // ==================== 商家接口 ====================

    @GetMapping("/merchant/my-products")
    @ApiOperation("获取当前商家的商品列表")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<IPage<ProductDetailVO>> getMyProducts(
            @RequestParam(defaultValue = "1") @Min(value = 1, message = "页码不能小于1") Integer pageNum,
            @RequestParam(defaultValue = "10") @Min(value = 1, message = "每页条数不能小于1") Integer pageSize) {
        try {
            // 获取当前登录用户ID
            Long userId = getUserId();
            if (userId == null) {
                return ApiResponse.error("用户未登录");
            }

            // 通过userId获取商家信息
            Merchant merchant = merchantService.getByUserId(userId);
            if (merchant == null) {
                return ApiResponse.error("商家信息不存在");
            }

            // 获取商家的商品列表
            IPage<Product> productPage = productService.getProductsByMerchant(merchant.getId(), pageNum, pageSize);
            
            // 转换为ProductDetailVO
            IPage<ProductDetailVO> voPage = new Page<>(productPage.getCurrent(), productPage.getSize(), productPage.getTotal());
            voPage.setRecords(productService.convertToProductDetailVO(productPage.getRecords()));
            
            return ApiResponse.success(voPage);
        } catch (Exception e) {
            log.error("获取商家商品列表失败: userId={}", getUserId(), e);
            return ApiResponse.error("获取商家商品列表失败");
        }
    }

    @PostMapping
    @ApiOperation("创建商品")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<Long> createProduct(@RequestBody @Validated({ProductDTO.Create.class}) ProductDTO productDTO) {
        try {
            // 根据hasSpecs标志决定使用哪个验证组
            if (!productDTO.getHasSpecs()) {
                // 手动验证单规格商品的必填字段
                if (productDTO.getSinglePrice() == null) {
                    return ApiResponse.error("单规格商品必须设置价格");
                }
                if (productDTO.getSingleStock() == null) {
                    return ApiResponse.error("单规格商品必须设置库存");
                }
                if (productDTO.getSinglePrice().compareTo(BigDecimal.ZERO) < 0) {
                    return ApiResponse.error("商品价格不能小于0");
                }
                if (productDTO.getSingleStock() < 0) {
                    return ApiResponse.error("商品库存不能小于0");
                }
            }
            return ApiResponse.success(productService.createProduct(productDTO));
        } catch (BusinessException e) {
            log.error("创建商品失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        } catch (Exception e) {
            log.error("创建商品失败", e);
            return ApiResponse.error("创建商品失败");
        }
    }

    @PutMapping("/{id}")
    @ApiOperation("更新商品")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<Boolean> updateProduct(@PathVariable Long id, @RequestBody @Valid ProductDTO productDTO) {
        try {
            productDTO.setId(id);
            boolean result = productService.updateProduct(productDTO);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商品失败: id={}, error={}", id, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品失败: id={}", id, e);
            return ApiResponse.error("更新商品失败");
        }
    }

    @PutMapping("/{id}/stock")
    @ApiOperation("更新商品库存")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<Boolean> updateStock(@PathVariable Long id, @RequestParam Integer stock) {
        try {
            boolean result = productService.updateStock(id, stock);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商品库存失败: id={}, stock={}, error={}", id, stock, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品库存失败: id={}, stock={}", id, stock, e);
            return ApiResponse.error("更新商品库存失败");
        }
    }

    @PostMapping("/upload/image")
    @ApiOperation("上传商品图片")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<String> uploadProductImage(@RequestParam("file") MultipartFile file) {
        try {
            String imageUrl = fileUploadUtils.uploadProductImage(file);
            return ApiResponse.success(imageUrl);
        } catch (BusinessException e) {
            log.error("上传商品图片失败: {}", e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("上传商品图片失败", e);
            return ApiResponse.error("上传商品图片失败");
        }
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除商品")
    @PreAuthorize("hasRole('MERCHANT')")
    public ApiResponse<Boolean> deleteProduct(@PathVariable @NotNull(message = "商品ID不能为空") Long id) {
        try {
            // 获取当前商家ID
            Long userId = getUserId();
            if (userId == null) {
                return ApiResponse.error("用户未登录");
            }

            // 通过userId获取商家信息
            Merchant merchant = merchantService.getByUserId(userId);
            if (merchant == null) {
                return ApiResponse.error("商家信息不存在");
            }

            // 验证商品是否属于当前商家
            ProductDetailVO product = productService.getProductDetail(id);
            if (product == null) {
                return ApiResponse.error("商品不存在");
            }
            if (!merchant.getId().equals(product.getMerchantId())) {
                return ApiResponse.error("无权删除该商品");
            }

            // 删除商品
            boolean result = productService.deleteProduct(id);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("删除商品失败: id={}, error={}", id, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("删除商品失败: id={}", id, e);
            return ApiResponse.error("删除商品失败");
        }
    }

    // ==================== 管理员接口 ====================

    @GetMapping("/merchant/{merchantId}")
    @ApiOperation("获取商家的商品列表")
    @PreAuthorize("hasRole('ADMIN')")  
    public ApiResponse<IPage<Product>> getMerchantProducts(
            @PathVariable Long merchantId,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        try {
            IPage<Product> products = productService.getProductsByMerchant(merchantId, pageNum, pageSize);
            return ApiResponse.success(products);
        } catch (Exception e) {
            log.error("获取商家商品列表失败: merchantId={}", merchantId, e);
            return ApiResponse.error("获取商家商品列表失败");
        }
    }

    @PutMapping("/{id}/recommend")
    @ApiOperation("更新商品推荐状态")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Boolean> updateRecommendStatus(@PathVariable Long id, @RequestParam Boolean isRecommend) {
        try {
            boolean result = productService.updateProductStatus(id, ProductService.ProductStatusType.RECOMMEND, isRecommend);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商品推荐状态失败: id={}, isRecommend={}, error={}", id, isRecommend, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品推荐状态失败: id={}, isRecommend={}", id, isRecommend, e);
            return ApiResponse.error("更新商品推荐状态失败");
        }
    }

    @PutMapping("/{id}/new")
    @ApiOperation("更新商品新品状态")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Boolean> updateNewStatus(@PathVariable Long id, @RequestParam Boolean isNew) {
        try {
            boolean result = productService.updateProductStatus(id, ProductService.ProductStatusType.NEW, isNew);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商品新品状态失败: id={}, isNew={}, error={}", id, isNew, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品新品状态失败: id={}, isNew={}", id, isNew, e);
            return ApiResponse.error("更新商品新品状态失败");
        }
    }

    @PutMapping("/{id}/hot")
    @ApiOperation("更新商品热销状态")
    @PreAuthorize("hasRole('ADMIN')")
    public ApiResponse<Boolean> updateHotStatus(@PathVariable Long id, @RequestParam Boolean isHot) {
        try {
            boolean result = productService.updateProductStatus(id, ProductService.ProductStatusType.HOT, isHot);
            return ApiResponse.success(result);
        } catch (BusinessException e) {
            log.error("更新商品热销状态失败: id={}, isHot={}, error={}", id, isHot, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品热销状态失败: id={}, isHot={}", id, isHot, e);
            return ApiResponse.error("更新商品热销状态失败");
        }
    }

    @PutMapping("/{id}/status")
    @ApiOperation("更新商品状态（上架/下架）")
    @PreAuthorize("hasAnyRole('ADMIN','MERCHANT')")
    public ApiResponse<Boolean> updateProductStatus(
            @PathVariable Long id,
            @RequestParam @NotNull(message = "状态不能为空") Boolean enabled) {
        try {
            // 获取当前用户角色
            boolean isAdmin = SecurityUtils.hasRole("ADMIN");
            Long merchantId = null;
            
            // 如果是商家,获取商家ID并验证商品所属权
            if (!isAdmin) {
                merchantId = getCurrentMerchantId();
                Product product = productService.getById(id);
                if (product == null) {
                    return ApiResponse.error("商品不存在");
                }
                if (!product.getMerchantId().equals(merchantId)) {
                    return ApiResponse.error("无权操作此商品");
                }
            }
            
            return ApiResponse.success(productService.updateProductStatus(id, ProductService.ProductStatusType.STATUS, enabled));
        } catch (BusinessException e) {
            log.error("更新商品状态失败: id={}, enabled={}, error={}", id, enabled, e.getMessage());
            return ApiResponse.error(e);
        } catch (Exception e) {
            log.error("更新商品状态失败: id={}, enabled={}", id, enabled, e);
            return ApiResponse.error("更新商品状态失败");
        }
    }



    // ==================== 公共方法 ====================

    /**
     * 创建简单的浏览行为DTO
     */
    private UserBehaviorDTO createSimpleBrowseDTO(Long productId, String source) {
        UserBehaviorDTO dto = new UserBehaviorDTO();
        dto.setProductId(productId);
        dto.setSource(source);
        dto.setBehaviorType("view");
        return dto;
    }
} 